/*
 * Middleware
 * Copyright (C) 2010/11
 * Riccardo Pulvirenti, Giuseppe Ravidà, Andrea Tino
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANDABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see http://www.gnu.org/licenses
 */

/*!
 * File: main.cpp
 */

//#define TEST_TEST
//#define TEST_UTILS
//#define TEST_CORE
//#define TEST_WORKFLOW
//#define TEST_TASK_DESCRIPTOR
//#define TEST_ADDRESS
//#define TEST_WORKERNETWORK
//#define TEST_PI
//#define TEST_WORKERDESCRIPTOR

#include <iostream>
#include <sstream>
#include <string>

#ifdef TEST_TEST
#include "task_descriptor_test.hpp"
#include "workflow_test.hpp"
#include "core_test.hpp"
#include "address_test.hpp"
#include "worker_network_test.hpp"
#include "performance_index_test.hpp"
#include "worker_descriptor_test.hpp"
#endif

#include "core.hpp"
#include "utils.hpp"

//-----------------------------------------------------------------------------
// Constants
/*!
 * Program parameters.
 */
const std::string kMainProgramName = "taskman-middleware";
const std::string kMainProgramVersion = "v1.0";
const std::string kMainProgramLic = "GNU GPL v3";
const std::string kMainProgramDates = "Nov-Dic 2010";
const std::string kMainProgramAuthors = "Riccardo Pulvirenti, Giuseppe Ravidà, Andrea Tino";
//-----------------------------------------------------------------------------
// Definitions
void tests();
int main(int argc, char** argv);
//-----------------------------------------------------------------------------
// Implementations
using namespace middleware;
/* Tests of classes */
void tests() {
#ifdef TEST_UTILS
	std::cout << "Testing Utils..." << std::endl;
	std::cout << "Start..." << std::endl;
	for (int i = 0; i < 100; i++) {
		std::cout << utils::GetRandomIntegralNumberStr(1,100000) << " - ";
		std::cout << utils::GetRandomIntegralNumber(100000) << std::endl;
	}
	std::cout << "End." << std::endl;
#endif
#ifdef TEST_TASK_DESCRIPTOR
	std::cout << "Testing Task Descriptor..." << std::endl;
	std::cout << "Start..." << std::endl;
	middleware::TaskDescriptorTest();
	middleware::TaskDescriptorSerializationTest();
	middleware::TaskDescriptorTCPSerializationTest();
	std::cout << "End." << std::endl;
#endif
#ifdef TEST_WORKFLOW
	std::cout << "Testing Workflow..." << std::endl;
	std::cout << "Start..." << std::endl;
	middleware::WorkflowTest();
	//middleware::WorkflowSerializationTest();
	//middleware::WorkflowTCPSerializationTest();
	std::cout << "End." << std::endl;
#endif
#ifdef TEST_CORE
	std::cout << "Testing CORE..." << std::endl;
	std::cout << "Start..." << std::endl;
	CoreTest();
	std::cout << "End." << std::endl;
#endif
#ifdef TEST_ADDRESS
	std::cout << "Testing Address..." << std::endl;
	std::cout << "Start..." << std::endl;
	AddressTest();
	std::cout << "End." << std::endl;
#endif
#ifdef TEST_WORKERNETWORK
	std::cout << "Testing WorkerNetwork..." << std::endl;
	std::cout << "Start..." << std::endl;
	WorkerNetworkTest();
	std::cout << "End." << std::endl;
#endif
#ifdef TEST_PI
	std::cout << "Testing PI..." << std::endl;
	std::cout << "Start..." << std::endl;
	CalculatePITest();
	std::cout << "End." << std::endl;
#endif
#ifdef TEST_WORKERDESCRIPTOR
	std::cout << "Testing WorkerDescriptor..." << std::endl;
	std::cout << "Start..." << std::endl;
	WorkerDescriptorTest();
	std::cout << "End." << std::endl;
#endif
}
/* Main */
int main(int argc, char** argv) {
#ifndef TEST_TEST
	// Normal execution
	std::cout << "Program starting..." << std::endl;
	std::cout << "Welcome!" << std::endl;
	std::cout << "Program: " << kMainProgramName << " " <<
			kMainProgramVersion << std::endl;
	std::cout << "Licensed under: " << kMainProgramLic << std::endl;
	std::cout << "Development dates: " << kMainProgramDates << std::endl;
	std::cout << "Developers: " << kMainProgramAuthors << std::endl;
	std::cout << "Loading Configuration file..." << std::endl;
	std::cout << "**********************************************" << std::endl;
	if (argc == 3) {
		// Two arguments provided ==> configuration file, logpostfix
		std::cout << "Configuration file to load: " << argv[1] <<
				", postfix to apply: " << argv[2] << "..." << std::endl;
		std::cout << "Creating CORE and passing control to it..." << std::endl;
		std::ostringstream osstr1, osstr2;
		osstr1 << argv[1];
		osstr2 << argv[2];
		CORE core(osstr1.str(), osstr2.str());
		core.exec(); /* EXECUTE */
	} else if (argc == 1) {
		std::cout << "Configuration file to load: default->" <<
				kConfigFileName << ", postfix will be random-generated" <<
				"..." << std::endl;
		std::cout << "Creating CORE and passing control to it..." << std::endl;
		CORE core;
		core.exec(); /* EXECUTE */
	} else {
		std::cout << "Invalid program execution call: " <<
				"usage: middleware.o [configfile_path]" << std::endl;
		return 1;
	}
	std::cout << "Program now shutting down..." << std::endl <<
			"Goodbye!" << std::endl;
#else
	// Test execution
	std::cout << "Program TEST starting..." << std::endl;
	tests();
#endif
}
